/*
 * IC Project - a prototype to test a hypothesis of collective intelligence
 * Copyright (C) 2012 Paolo Conte - paolo@concavi.net
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * 
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package org.ix.data.entities;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Iterator;
import org.ix.data.manager.POJOManager;

/**
 * Generic class used to manage hierarchical structures.
 * Used in ItemTypes and Events
 * @author
 */
public class HNode implements Cloneable, Serializable{

    private String name;
    private String value;
    private ArrayList<HNode> childs;
    private HNode father;

    public HNode(String name, String value) {
        this.name = name;
        this.value = value;
        this.childs = new ArrayList<HNode>();
    }

    public ArrayList<HNode> setChilds(ArrayList<HNode> childs) {
        ArrayList<HNode> oldChilds = this.childs;
        this.childs = childs;
        return oldChilds;
    }

    public boolean hasChilds() {
        return (childs.size() > 0);
    }

    public String getName() {
        return this.name;
    }

    public void setFather(HNode father) {
        this.father = father;
    }

    public int getNodeIndex(HNode node) {
        return childs.indexOf(node);
    }

    public HNode getChild(int index) {
        HNode node = childs.get(index);
        return node;
    }

    public HNode removeChild(HNode node) {
        return (HNode) childs.remove(this.getNodeIndex(node));
    }

    public boolean addChild(HNode node) {
        if (childExists(node)) {
            return false;
        } else {
            node.setFather(this);
            childs.add(node);
            return true;
        }
    }

    /**
     * Search recursively a node by name
     * @param name The node name
     * @return A node or null if not found
     */
    public HNode getChild(String name) {
        if (name == null) {
            return null;
        }
        Iterator iterChilds = childs.iterator();
        while (iterChilds.hasNext()) {
            HNode node = (HNode) iterChilds.next();
            if (node.getName() == null) {
                continue;
            }
            if (name.equals(node.getName())) {
                return node;
            } else {
                HNode childNode = node.getChild(name);
                if (childNode != null) {
                    return childNode;
                }
            }
        }
        return null;
    }

    public boolean childExists(HNode node) {
        boolean found = false;
        Iterator iterChilds = childs.iterator();
        while (iterChilds.hasNext()) {
            HNode child = (HNode) iterChilds.next();

            //dbgU.logga("checkPresenza: " + nodo + " = " + figlio + " = " + (nodo.equals(figlio)), DebugUtil.WARNING);
            if (node.equals(child)) {
                return true;
            } else {
                found = child.childExists(node);
            }
        }
        return found;
    }

    public Object clone()
	{
		ArrayList<HNode> cloneChilds = new ArrayList<HNode>(childs.size());
		for(int idx=0; idx<childs.size(); idx++)
		{
			cloneChilds.add((HNode)childs.get(idx));
		}

		HNode clone = new HNode(name, value);
        clone.setChilds(cloneChilds);
		clone.setFather(father);
		
		return clone;
	}

    public String toXMLString()
	{
		return toXMLString(false, false);
	}

    public String toXMLString(boolean indent)
	{
		return toXMLString(indent, false);
	}

	public String toXMLString(boolean indent, boolean useHTMLEntities)
	{
		String xml = "\n";
        String lft = useHTMLEntities?"&lt;":"<";
        String rgt = useHTMLEntities?"&gt;":">";

		if(indent) {
            xml += "\t";
        }

		xml += lft + name + rgt + value;

		Iterator iterChilds = childs.iterator();
		while(iterChilds.hasNext())
		{
			xml += ((HNode)iterChilds.next()).toXMLString(indent, useHTMLEntities);
		}

		xml += lft + "/" + name + rgt + "\n";

		return xml;
	}

    // TODO
    public String toJSONString()
	{
		String json = "{";

		json += POJOManager.escape(name) + ":\"" + POJOManager.escape(value) + "\"";

        json += ",";

		Iterator iterChilds = childs.iterator();
		while(iterChilds.hasNext())
		{
			json += ((HNode)iterChilds.next()).toJSONString();
		}

        json = json.substring(0, json.length()-1);
        json += "}";

		return json;
	}
}
